package proxy

import (
	"context"
	"fmt"
	"github.com/Dreamacro/clash/adapter"
	"github.com/Dreamacro/clash/constant"
	"github.com/ghodss/yaml"
	"github.com/lytdev/go-mykit/grandom"
	"net"
	"net/url"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

type transportConn struct {
	NetConn net.Conn
	Proxy   constant.Proxy
}

func NewRandomTransportProxy(filePath, host string) *transportConn {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
	defer cancel()

	addr, err := urlToMetadata(host)
	if err != nil {
		panic(err.Error())
	}
	px := randomProxySimple(filePath)
	proxy, err := adapter.ParseProxy(px)
	conn, err := proxy.DialContext(ctx, &addr) // 建立到proxy server的connection，对Proxy的类别做了自适应相当于泛型
	if err != nil {
		return NewRandomTransportProxy(filePath, host)
	}
	return &transportConn{NetConn: conn, Proxy: proxy}
}

func urlToMetadata(rawURL string) (addr constant.Metadata, err error) {
	u, err := url.Parse(rawURL)
	if err != nil {
		return
	}

	port := u.Port()
	if port == "" {
		switch u.Scheme {
		case "https":
			port = "443"
		case "http":
			port = "80"
		default:
			err = fmt.Errorf("%s scheme not Support", rawURL)
			return
		}
	}

	portInt, err := strconv.ParseUint(port, 10, 16)

	addr = constant.Metadata{
		Host:    u.Hostname(),
		DstIP:   nil,
		DstPort: constant.Port(portInt),
	}
	return
}

func randomProxySimple(filePath string) (str map[string]interface{}) {
	if len(clash.Proxy) == 0 {
		filepath.Walk(filePath, func(path string, info os.FileInfo, err error) error {
			if info.IsDir() {
				return nil
			}
			if strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml") {
				content, _ := os.ReadFile(path)
				p := proxyYaml{}
				yaml.Unmarshal(content, &p)
				clash.Proxy = append(clash.Proxy, p.Proxy...)
			}
			return nil
		})
	}
	l := len(clash.Proxy)
	randomInt := grandom.RandomIntRange(0, l-1)
	return clash.Proxy[randomInt]
}

var clash proxyYaml

type proxyYaml struct {
	Proxy []map[string]interface{} `json:"proxies" yaml:"proxies"`
}
